package com.zlcx.tz.live.web;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.zlcx.tz.live.client.UserClient;
import com.zlcx.tz.live.client.vo.LiveGatherVO;
import com.zlcx.tz.live.common.annotation.AutoLog;
import com.zlcx.tz.live.common.annotation.RepeatSubmit;
import com.zlcx.tz.live.common.thread.MdcRunable;
import com.zlcx.tz.live.constant.AppEnum;
import com.zlcx.tz.live.domain.LiveFree;
import com.zlcx.tz.live.domain.LiveRoomInfo;
import com.zlcx.tz.live.domain.LiveSwitched;
import com.zlcx.tz.live.enums.RoomJoinStatus;
import com.zlcx.tz.live.enums.RoomUserRole;
import com.zlcx.tz.live.exception.BusinessException;
import com.zlcx.tz.live.exception.CheckParamException;
import com.zlcx.tz.live.exception.CheckRunException;
import com.zlcx.tz.live.exception.VideoLimitException;
import com.zlcx.tz.live.service.impl.LiveRoomJoinRecordService;
import com.zlcx.tz.live.service.impl.LiveRoomPublisherService;
import com.zlcx.tz.live.service.impl.LiveRoomService;
import com.zlcx.tz.live.service.task.TaskService;
import com.zlcx.tz.live.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.util.Asserts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.zlcx.tz.live.common.annotation.AutoLog.Level.DEBUG;
import static com.zlcx.tz.live.common.config.RedisConfig.CacheKeys.ROOM_FREE_NUM;
import static com.zlcx.tz.live.constant.ResultStatus.*;

/**
 * <p>上麦</p>
 * <PRE>
 * <BR>    修改记录
 * <BR>-----------------------------------------------
 * <BR>    修改日期         修改人          修改内容
 * </PRE>
 *
 * @author zl
 * @version 1.0
 * @date Created in 2019/4/18 10:26UserLiveStateVO
 * @copyright: Copyright (c) founders
 */
@Controller
@Slf4j
@Api(tags = {"上麦"}, description = "上麦相关接口")
@RequestMapping("publisher")
public class LiveRoomPublisherController extends BaseController {


    @Autowired
    LiveRoomPublisherService publisherService;

    @Autowired
    HttpServletRequest request;

    @Autowired
    LiveRoomJoinRecordService liveRoomJoinRecordService;

    @Autowired
    LiveRoomService liveRoomService;

    @Autowired
    private TaskService taskService;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    private UserClient userClient;

    private Logger traceLoger = LoggerFactory.getLogger("traceloger");

    @AutoLog
    @PreAuthorize("isAuthenticated()")
    @RepeatSubmit
    @ApiOperation(value = "申请上麦", notes = "申请上麦")
    @PostMapping(value = "/apply/{roomId}/{userId}")
    public ResponseEntity<ResultVO> applyPublish(@ApiParam(value = "token", required = true) @RequestHeader String authorization,
                                                 @ApiParam(value = "房间id", required = true) @PathVariable Long roomId,
                                                 @ApiParam(value = "用户id", required = true) @PathVariable Long userId
    ) {

        traceLoger.info("【用户操作】 房间【{}】用户【{}】申请上麦", roomId, userId);
        LiveSwitched switched = liveRoomJoinRecordService.getSwitched(1L);
        if (switched.getSwitched().intValue() == LiveSwitched.SwitchEnum.ON.code.intValue()) {
            //开关打开，然后检查是否是vip用户
            throw new VideoLimitException("该版本已经停止连麦服务，请下载最新版本APP！");
        }
        RoomPublisherVO roomPublisherVO = publisherService.applyPublish(roomId, userId, null);
        return ResponseEntity.ok(successState());

    }


    @AutoLog
    @PreAuthorize("isAuthenticated()")
    @RepeatSubmit
    @ApiOperation(value = "3.0版本申请上麦", notes = "3.0版本申请上麦")
    @PostMapping(value = "/apply/v3")
    public ResponseEntity<ResultVO> applyPublishV3(@RequestBody ApplyPublishVO publish) {

        Asserts.check(Objects.nonNull(publish.getRoomId()), "房间id不能为空！");
        Asserts.check(Objects.nonNull(publish.getUserId()), "用户id不能为空！");
        Asserts.check(Objects.nonNull(publish.getStudyContent()), "学习名称不能为空！");

        traceLoger.info("【用户操作】 申请上麦 {}", publish);
        //TODO  校验是否vip会员，前三天逻辑等
        try {
            //检查是否是vip用户
//            VipUserVO vipUserVO = liveRoomJoinRecordService.checkVip(publish.getUserId());
            LiveGatherVO gather = userClient.gather(publish.getUserId()).getData();
            if (gather.getIsAllow()) {
                LiveRoomInfo liveRoomInfo = liveRoomService.getRoomInfoById(publish.getRoomId());
                if (Objects.isNull(liveRoomInfo)) {
                    throw new CheckParamException("房间已经关闭");
                }
                if (liveRoomInfo.getOnlyVipApply() == 1) {
                    return ResponseEntity.ok(new ResultVO(NO_VIP_APPLY_ROOM_ERROR.getCode(), NO_VIP_APPLY_ROOM_ERROR.getInfo()));
                }
                //每天两次免费次数是否用完
//                Object numObj = redisTemplate.opsForValue().get(ROOM_FREE_NUM + publish.getUserId());
//                log.debug("numObj = {}", numObj);
//                if (Objects.nonNull(numObj)) {
//                    int useNum = Integer.parseInt(numObj.toString());
//                    LiveFree liveFree = liveRoomJoinRecordService.getLiveFree(1L);
//                    if (useNum >= liveFree.getTotalFreeNum()) {
//                        return ResponseEntity.ok(new ResultVO(LIVE_NUMS_USE_ERROR.getCode(), LIVE_NUMS_USE_ERROR.getInfo()));
//                    }
//                }
            } else {
                return ResponseEntity.ok(new ResultVO(VIP_USE_OVER_ERROR.getCode(), VIP_USE_OVER_ERROR.getInfo()));
            }
            publisherService.applyPublish(publish.getRoomId(), publish.getUserId(), publish.getStudyContent());
            return ResponseEntity.ok(successState());
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("申请上麦失败，roomId={},userId={}", publish.getRoomId(), publish.getUserId(), e);
            throw new CheckRunException("申请上麦失败!", e);
        }

    }

    @AutoLog(logLevel = DEBUG)
    @PreAuthorize("isAuthenticated()")
    @RepeatSubmit
    @ApiOperation(value = "取消申请上麦", notes = "取消申请上麦")
    @PutMapping(value = "/cancel/{roomId}/{userId}")
    public ResponseEntity<ResultVO> cancelApplyPublish(@ApiParam(value = "token", required = true) @RequestHeader String authorization,
                                                       @ApiParam(value = "房间id", required = true) @PathVariable Long roomId,
                                                       @ApiParam(value = "用户id", required = true) @PathVariable Long userId) {

        traceLoger.info("【用户操作】 房间【{}】用户【{}】取消申请上麦", roomId, userId);
        try {

            RoomPublisherVO roomPublisherVO = publisherService.cancelApplyPublish(roomId, userId);

            return ResponseEntity.ok(successState());

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("取消申请上麦失败，roomId={},userId={}", roomId, userId, e);
            throw new CheckRunException("取消申请上麦失败!", e);
        }

    }

    @AutoLog
    @PreAuthorize("isAuthenticated()")
    @RepeatSubmit
    @ApiOperation(value = "同意上麦", notes = "同意上麦申请")
    @PutMapping(value = "/agree/{hostUserId}/{roomId}/{userId}")
    public ResponseEntity<ResultVO> agreeApplyPublish(@ApiParam(value = "token", required = true) @RequestHeader String authorization,
                                                      @ApiParam(value = "房间id", required = true) @PathVariable Long roomId,
                                                      @ApiParam(value = "用户id", required = true) @PathVariable Long userId,
                                                      @ApiParam(value = "房主id", required = true) @PathVariable Long hostUserId,
                                                      HttpServletRequest request) {

        traceLoger.info("【用户操作】 房间【{}】房主【{}】同意 用户【{}】上麦", roomId, hostUserId, userId);

        try {

            publisherService.agreeApplyPublish(roomId, userId, hostUserId);
//            VipUserVO vipUserVO = liveRoomJoinRecordService.checkVip(userId);
            //用来模拟真实app访问来判断用户来自哪个app
            UserVO userInfo = userClient.getUserInfo(userId).getData();
            if(Objects.nonNull(userInfo) && StringUtils.isNotBlank(userInfo.getApp())){
                MdcRunable.setAppIfAbsent(userInfo.getApp());
            }

            LiveGatherVO gather = userClient.gather(userId).getData();
            if (gather.getIsAllow()) {
                //修改每天免费次数--redis
                LocalDateTime midnight = LocalDateTime.now().plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
                long seconds = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight);
                if (Objects.nonNull(gather.getLiveExperience())) {
                    Object numObj = redisTemplate.opsForValue().get(ROOM_FREE_NUM + userId);
                    if (Objects.isNull(numObj)) {
                        redisTemplate.opsForValue().set(ROOM_FREE_NUM + userId, 1, seconds, TimeUnit.SECONDS);
                    } else {
                        redisTemplate.opsForValue().increment(ROOM_FREE_NUM + userId, 1);
                    }
                }
            }
            return ResponseEntity.ok(successState());
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("同意上麦失败，roomId={},userId={},hostUserId={}", roomId, userId, hostUserId, e);
            throw new CheckRunException("同意上麦失败!", e);
        }

    }

    @AutoLog
    @PreAuthorize("isAuthenticated()")
    @RepeatSubmit
    @ApiOperation(value = "下麦", notes = "下麦")
    @PutMapping(value = "/quit/{roomId}/{userId}")
    public ResponseEntity<ResultVO> quitPublish(@ApiParam(value = "token", required = true) @RequestHeader String authorization,
                                                @ApiParam(value = "房间id", required = true) @PathVariable Long roomId,
                                                @ApiParam(value = "用户id", required = true) @PathVariable Long userId) {

        traceLoger.info("【用户操作】 房间【{}】用户【{}】下麦", roomId, userId);

        try {
            log.info("下麦 roomId = {} userId = {}", roomId, userId);
            RoomPublisherVO roomPublisherVO = publisherService.quitPublish(roomId, userId, true);

            return ResponseEntity.ok(successState());

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("下麦失败，roomId={},userId={}", roomId, userId, e);
            throw new CheckRunException("下麦失败!", e);
        }

    }

    @AutoLog
    @PreAuthorize("isAuthenticated()")
    @RepeatSubmit
    @ApiOperation(value = "全员禁麦操作", notes = "全员禁麦操作")
    @PutMapping(value = "/operateAllMic/{hostUserId}/{roomId}")
    public ResponseEntity<ResultVO> operateAllMic(@ApiParam(value = "token", required = true) @RequestHeader String authorization,
                                                  @ApiParam(value = "房间id", required = true) @PathVariable Long roomId,
                                                  @ApiParam(value = "房主id", required = true) @PathVariable Long hostUserId,
                                                  @ApiParam(value = "操作：0-关闭，1-打开", required = true) @RequestParam Integer micState) {

        traceLoger.info("【用户操作】 房间【{}】房主【{}】全员禁麦操作【{}】", roomId, hostUserId, micState);
        try {
            publisherService.operateAllMic(roomId, hostUserId, micState);

            return ResponseEntity.ok(successState());

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("全员禁麦操作失败，hostUserId={},roomId={},micState={}", hostUserId, roomId, micState, e);
            throw new CheckRunException("全员禁麦操作失败!", e);
        }

    }

    @AutoLog
    @PreAuthorize("isAuthenticated()")
    @RepeatSubmit
    @ApiOperation(value = "自己麦克操作", notes = "自己麦克操作")
    @PutMapping(value = "/operateSelfMic/{roomId}/{userId}")
    public ResponseEntity<ResultVO> operateSelfMic(@ApiParam(value = "token", required = true) @RequestHeader String authorization,
                                                   @ApiParam(value = "房间id", required = true) @PathVariable Long roomId,
                                                   @ApiParam(value = "用户id", required = true) @PathVariable Long userId,
                                                   @ApiParam(value = "操作：0-关闭，1-打开", required = true) @RequestParam Integer micState) {

        traceLoger.info("【用户操作】 房间【{}】用户【{}】麦克操作", roomId, userId, micState);
        try {

            publisherService.operateSelfMic(roomId, userId, micState);

            return ResponseEntity.ok(successState());

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("自己麦克操作失败，userId={},roomId={},micState={}", userId, roomId, micState, e);
            throw new CheckRunException("自己麦克操作失败!", e);
        }

    }

    @AutoLog(logLevel = DEBUG)
    @PreAuthorize("isAuthenticated()")
    @ApiOperation(value = "查看上麦申请列表", notes = "查看上麦申请列表", response = RoomPublisherVO.class, responseContainer = "List")
    @GetMapping(value = "/applyList/{hostUserId}/{roomId}")
    public ResponseEntity<ResultVO> applyList(@ApiParam(value = "token", required = true) @RequestHeader String authorization,
                                              @ApiParam(value = "房间id", required = true) @PathVariable Long roomId,
                                              @ApiParam(value = "房主id", required = true) @PathVariable Long hostUserId) {

        traceLoger.info("【用户操作】 房间【{}】房主【{}】查看上麦申请列表", roomId, hostUserId);
        try {

            List<RoomPublisherVO> list = publisherService.applyList(roomId, hostUserId);
            return ResponseEntity.ok(successState(list));

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("查看上麦申请列表失败，hostUserId={},roomId={}", hostUserId, roomId, e);
            throw new CheckRunException("查看上麦申请列表失败!", e);
        }

    }

    @AutoLog(logLevel = DEBUG)
    @PreAuthorize("isAuthenticated()")
    @ApiOperation(value = "确认取消申请记录已读", notes = "确认取消申请记录已读")
    @PostMapping(value = "/ackCancelApplyPublish/{hostUserId}/{roomId}")
    public ResponseEntity<ResultVO> ackCancelApplyPublish(@ApiParam(value = "token", required = true) @RequestHeader String authorization,
                                                          @ApiParam(value = "房间id", required = true) @PathVariable Long roomId,
                                                          @ApiParam(value = "房主id", required = true) @PathVariable Long hostUserId,
                                                          @ApiParam(value = "申请记录id", required = true) @RequestBody List<Long> ids) {

        traceLoger.info("【用户操作】 房间【{}】房主【{}】确认取消申请已读 【{}】", roomId, hostUserId, ids);

        try {
            publisherService.ackCancelApplyPublish(roomId, hostUserId, ids);
            return ResponseEntity.ok(successState());
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("确认取消申请记录已读失败，hostUserId={},roomId={},idStr={}", hostUserId, roomId, JSON.toJSONString(ids), e);
            throw new CheckRunException("确认取消申请记录已读失败!", e);
        }

    }

    @AutoLog(logLevel = DEBUG)
    @PreAuthorize("isAuthenticated()")
    @ApiOperation(value = "邀请上麦列表", notes = "邀请上麦列表", response = InviteListVO.class, responseContainer = "List")
    @GetMapping(value = "/inviteList/{userId}")
    public ResponseEntity<ResultVO> inviteList(@ApiParam(value = "token", required = true) @RequestHeader String authorization,
                                               @ApiParam(value = "用户id", required = true) @PathVariable Long userId) {

        try {

            List<InviteListVO> list = publisherService.inviteList(userId);
            return ResponseEntity.ok(successState(list));

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("邀请上麦列表失败，userId={}", userId, e);
            throw new CheckRunException("邀请上麦列表失败!", e);
        }

    }

    @AutoLog(logLevel = DEBUG)
    @PreAuthorize("isAuthenticated()")
    @RepeatSubmit
    @ApiOperation(value = "邀请上麦", notes = "邀请上麦")
    @PostMapping(value = "/invite/{roomId}/{userId}")
    public ResponseEntity<ResultVO> invitePublish(@ApiParam(value = "token", required = true) @RequestHeader String authorization,
                                                  @ApiParam(value = "房间id", required = true) @PathVariable Long roomId,
                                                  @ApiParam(value = "用户id", required = true) @PathVariable Long userId,
                                                  @ApiParam(value = "分享给用户id(多个以英文逗号分割)") @RequestParam(required = false) String shareToUserIds,
                                                  @ApiParam(value = "分享给群组id(多个以英文逗号分割)") @RequestParam(required = false) String shareToGroupIds) {
        List<Long> shareToUserList = Lists.newArrayList();
        List<String> shareToGroupList = Lists.newArrayList();


        if (StringUtils.isBlank(shareToUserIds) && StringUtils.isBlank(shareToGroupIds)) {
            String requestBody = "";
            try {
                requestBody = IOUtils.toString(request.getInputStream(), Charset.forName("UTF-8"));
                if (StringUtils.isNotBlank(requestBody)) {
                    JSONObject jsonObject = JSON.parseObject(requestBody);
                    shareToUserIds = jsonObject.getString("shareToUserIds");
                    shareToGroupIds = jsonObject.getString("shareToGroupIds");
                }
                log.debug("[invitePublish] requestBody={},shareToUserIds={},shareToGroupIds={}", requestBody, shareToUserIds, shareToGroupIds);
            } catch (Exception e) {
                log.error("[invitePublish]读取请求体失败！，requestBody={},e={}", requestBody, e);
                throw new CheckParamException("分享参数错误：" + requestBody);
            }
        }

        if (StringUtils.isNotBlank(shareToUserIds)) {
            try {
                String[] tmps = shareToUserIds.split(",");
                for (String str : tmps) {
                    shareToUserList.add(Long.valueOf(str));
                }
            } catch (Exception e) {
                throw new CheckParamException("分享用户参数错误：" + shareToUserIds);
            }
        }
        if (StringUtils.isNotBlank(shareToGroupIds)) {
            shareToGroupList = Lists.newArrayList(shareToGroupIds.split(","));
        }

        try {
            publisherService.invitePublish(roomId, userId, shareToUserList, shareToGroupList);

            return ResponseEntity.ok(successState());

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("邀请上麦失败，roomId={},userId={}", roomId, userId, e);
            throw new CheckRunException("邀请上麦失败!", e);
        }

    }

//
//    @ApiOperation(value = "开始学习计时", notes = "开始学习计时")
//    @PostMapping(value = "/startTask/{roomId}/{userId}")
//    public ResponseEntity<ResultVO> startTask(
//                                              @ApiParam(value = "房间id", required = true) @PathVariable Long roomId,
//                                              @ApiParam(value = "用户id", required = true) @PathVariable Long userId) {
//
//        try {
//
//            publisherService.startLearnTask(userId, roomId);
//            return ResponseEntity.ok(successState());
//
//        } catch (BusinessException e) {
//            throw e;
//        } catch (Exception e) {
//            log.error("学习开始计时失败，roomId={},userId={},e={}", roomId, userId, e);
//            throw new CheckRunException("学习开始计时失败!", e);
//        }
//
//    }

//    @ApiOperation(value = "结束学习计时", notes = "结束学习计时")
//    @PostMapping(value = "/stopTask/{roomId}/{userId}")
//    public ResponseEntity<ResultVO> stopLearnTask(
//                                                  @ApiParam(value = "房间id", required = true) @PathVariable Long roomId,
//                                                  @ApiParam(value = "用户id", required = true) @PathVariable Long userId) {
//
//        try {
//
//            publisherService.stopLearnTask(userId, roomId);
//            return ResponseEntity.ok(successState());
//
//        } catch (BusinessException e) {
//            throw e;
//        } catch (Exception e) {
//            log.error("结束学习计时失败，roomId={},userId={},e={}", roomId, userId, e);
//            throw new CheckRunException("结束学习计时失败!", e);
//        }
//
//    }

    //    @PreAuthorize("isAuthenticated()")
    @AutoLog(logLevel = DEBUG)
    @ApiOperation(value = "连麦心跳", notes = "连麦心跳")
    @PostMapping(value = "/liveTask/{roomId}/{userId}")
    public ResponseEntity<ResultVO> liveTask(@ApiParam(value = "token") @RequestHeader(required = false) String authorization,
                                             @ApiParam(value = "房间id", required = true) @PathVariable Long roomId,
                                             @ApiParam(value = "用户id", required = true) @PathVariable Long userId) {

        try {

            JSONObject jsonObject = publisherService.liveTask(userId, roomId);
            return ResponseEntity.ok(successState(jsonObject));

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("连麦心跳失败，roomId={},userId={}", roomId, userId, e);
            throw new CheckRunException("连麦心跳失败!", e);
        }

    }

    @AutoLog(logLevel = DEBUG)
    @ApiOperation(value = "查询连麦记录", notes = "查询连麦记录", response = RoomPublisherVO.class, responseContainer = "Map")
    @GetMapping(value = "/recordInfo/{publishRecordId}")
    public ResponseEntity<ResultVO> recordInfo(
            @ApiParam(value = "连麦记录id", required = true) @PathVariable Long publishRecordId) {

        try {
            RoomPublisherVO publisherVO = publisherService.findPublisherRecord(publishRecordId);
            return ResponseEntity.ok(successState(publisherVO));

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("查询连麦记录，publishRecordId={}", publishRecordId, e);
            throw new CheckRunException("查询连麦记录!", e);
        }

    }

    @AutoLog(logLevel = DEBUG)
    @ApiOperation(value = "房间及用户的状态信息", notes = "返回房间及用户的状态信息规则：如果不传userId则和用户相关的状态（inRoomState，userRole，publisherState）不返回；" +
            "如果不传roomId，则只有用户在房间的情况下会返回房间信息（roomId，roomValidState,roomName）", response = StatusVO.class, responseContainer = "Map")
    @GetMapping(value = "/statusInfo")
    public ResponseEntity<ResultVO> statusInfo(
            @ApiParam(value = "房间id") @RequestParam(required = false) Long roomId,
            @ApiParam(value = "用户id") @RequestParam(required = false) Long userId) {

        try {

            StatusVO statusVO = publisherService.statusInfo(userId, roomId);
            return ResponseEntity.ok(successState(statusVO));

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("房间及用户的状态信息失败，roomId={},userId={}", roomId, userId, e);
            throw new CheckRunException("房间及用户的状态信息失败!", e);
        }

    }

    @AutoLog(logLevel = DEBUG)
    @PreAuthorize("isAuthenticated()")
    @PostMapping("/live-state")
    public ResponseEntity<ResultVO<List<UserLiveStateVO>>> findLiveState(@RequestBody List<Long> userIds) {
        List<UserLiveStateVO> recordList = liveRoomJoinRecordService.findByUserRoleAndJoinStateAndUserIdIn(RoomUserRole.OWNER.getCode(), RoomJoinStatus.IN.getCode(), userIds);
        return ResponseEntity.ok(successState(recordList));
    }

    @AutoLog(logLevel = DEBUG)
    @PreAuthorize("isAuthenticated()")
    @PostMapping("/live/list/audience")
    public ResponseEntity<ResultVO<List<UserLiveStateVO>>> findAudience(@RequestBody List<Long> userIds) {
        List<UserLiveStateVO> recordList = liveRoomJoinRecordService.findByUserRoleAndJoinStateAndUserIdIn(RoomUserRole.AUDIENCE.getCode(), RoomJoinStatus.IN.getCode(), userIds);
        return ResponseEntity.ok(successState(recordList));
    }

    @AutoLog
    @ApiOperation(value = "备份已关闭房间信息，凌晨4点执行", notes = "备份已关闭房间信息，凌晨4点执行")
    @GetMapping("/close-room/backup")
    public ResultVO backupCloseRoom() {
        taskService.backupCloseRoom();
        return successState(null);
    }

    @AutoLog(logLevel = DEBUG)
    @ApiOperation(value = "根据用户id查询用户所在房间号, 服务端调用", notes = "根据用户id查询用户所在房间号, 服务端调用", response = InviteListVO.class, responseContainer = "List")
    @GetMapping(value = "/room/list")
    public ResponseEntity<ResultVO<List<RoomPublisherVO>>> roomInfos(@ApiParam(value = "用户ids", required = true) @RequestParam List<Long> userIds) {

        try {
            return ResponseEntity.ok(successState(publisherService.findRoomListByUserIds(userIds)));
        } catch (Exception e) {
            log.error("根据用户id查询用户所在房间号, 调用失败，userId={}", userIds, e);
            throw new CheckRunException("根据用户id查询用户所在房间号, 调用失败!", e);
        }

    }

}
